   package mars.mips.instructions;
   import mars.simulator.*;
   import mars.mips.hardware.*;
   import mars.mips.instructions.syscalls.*;
   import mars.*;
   import mars.util.*;
   import java.util.*;
   import java.io.*;
	
	/*
Copyright (c) 2003-2008,  Pete Sanderson and Kenneth Vollmar

Developed by Pete Sanderson (psanderson@otterbein.edu)
and Kenneth Vollmar (kenvollmar@missouristate.edu)

Permission is hereby granted, free of charge, to any person obtaining 
a copy of this software and associated documentation files (the 
"Software"), to deal in the Software without restriction, including 
without limitation the rights to use, copy, modify, merge, publish, 
distribute, sublicense, and/or sell copies of the Software, and to 
permit persons to whom the Software is furnished to do so, subject 
to the following conditions:

The above copyright notice and this permission notice shall be 
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

(MIT license, http://www.opensource.org/licenses/mit-license.html)
 */

/**
 * The list of Instruction objects, each of which represents a MIPS instruction.
 * The instruction may either be basic (translates into binary machine code) or
 * extended (translates into sequence of one or more basic instructions).
 *
 * @author Pete Sanderson and Ken Vollmar
 * @version August 2003-5
 */

    public class InstructionSet
   {
      private ArrayList instructionList;
      private SyscallLoader syscallLoader;
    /**
     * Creates a new InstructionSet object.
     */
       public InstructionSet()
      {
         instructionList = new ArrayList();
      
      }
    /**
     * Retrieve the current instruction set.
     */
       public ArrayList getInstructionList()
      {
         return instructionList;
      
      }
    /**
     * Adds all instructions to the set.  A given extended instruction may have
     * more than one Instruction object, depending on how many formats it can have.
     * @see Instruction
     * @see BasicInstruction
     * @see ExtendedInstruction
     */
       public void populate()
      {
        /* Here is where the parade begins.  Every instruction is added to the set here.*/
      
        // ////////////////////////////////////   BASIC INSTRUCTIONS START HERE ////////////////////////////////
      
         instructionList.add(
                new BasicInstruction("nop",
            	 "Null operation",
                BasicInstructionFormat.R_FORMAT,
                "000000 00000 00000 00000 00000 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                  	// Hey I like this so far!
                  }
               }));
         instructionList.add(
                new BasicInstruction("add $1,$2,$3",
            	 "Addition with overflow",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int add1 = RegisterFile.getValue(operands[1]);
                     int add2 = RegisterFile.getValue(operands[2]);
                     int sum = add1 + add2;
                  // overflow on A+B detected when A and B have same sign and A+B has other sign.
                     if ((add1 >= 0 && add2 >= 0 && sum < 0)
                        || (add1 < 0 && add2 < 0 && sum >= 0))
                     {
                        throw new ProcessingException(statement,
                            "arithmetic overflow",Exceptions.ARITHMETIC_OVERFLOW_EXCEPTION);
                     }
                     RegisterFile.updateRegister(operands[0], sum);
                  }
               }));
         instructionList.add(
                new BasicInstruction("sub $1,$2,$3",
            	 "Subtraction with overflow",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int sub1 = RegisterFile.getValue(operands[1]);
                     int sub2 = RegisterFile.getValue(operands[2]);
                     int dif = sub1 - sub2;
                  // overflow on A-B detected when A and B have opposite signs and A-B has B's sign
                     if ((sub1 >= 0 && sub2 < 0 && dif < 0)
                        || (sub1 < 0 && sub2 >= 0 && dif >= 0))
                     {
                        throw new ProcessingException(statement,
                            "arithmetic overflow",Exceptions.ARITHMETIC_OVERFLOW_EXCEPTION);
                     }
                     RegisterFile.updateRegister(operands[0], dif);
                  }
               }));
         instructionList.add(
                new BasicInstruction("addi $1,$2,-100",
            	 "Addition immediate with overflow",
                BasicInstructionFormat.I_FORMAT,
                "001000 sssss fffff tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int add1 = RegisterFile.getValue(operands[1]);
                     int add2 = operands[2] << 16 >> 16;
                     int sum = add1 + add2;
                  // overflow on A+B detected when A and B have same sign and A+B has other sign.
                     if ((add1 >= 0 && add2 >= 0 && sum < 0)
                        || (add1 < 0 && add2 < 0 && sum >= 0))
                     {
                        throw new ProcessingException(statement,
                            "arithmetic overflow",Exceptions.ARITHMETIC_OVERFLOW_EXCEPTION);
                     }
                     RegisterFile.updateRegister(operands[0], sum);
                  }
               }));
         instructionList.add(
                new BasicInstruction("addu $1,$2,$3",
            	 "Addition unsigned without overflow",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        + RegisterFile.getValue(operands[2]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("subu $1,$2,$3",
            	 "Subtraction unsigned without overflow",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        - RegisterFile.getValue(operands[2]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("addiu $1,$2,-100",
            	 "Addition immediate unsigned without overflow",
                BasicInstructionFormat.I_FORMAT,
                "001001 sssss fffff tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        + (operands[2] << 16 >> 16));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mult $1,$2",
            	 "Multiplication",
                BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 011000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     long product = (long) RegisterFile.getValue(operands[0])
                        * (long) RegisterFile.getValue(operands[1]);
                  // Register 33 is HIGH and 34 is LOW
                     RegisterFile.updateRegister(33, (int) (product >> 32));
                     RegisterFile.updateRegister(34, (int) ((product << 32) >> 32));
                  }
               }));
         instructionList.add(
                new BasicInstruction("multu $1,$2",
            	 "Multipication unsigned",
                BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 011001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     long product = (((long) RegisterFile.getValue(operands[0]))<<32>>>32)
                        * (((long) RegisterFile.getValue(operands[1]))<<32>>>32);
                  // Register 33 is HIGH and 34 is LOW
                     RegisterFile.updateRegister(33, (int) (product >> 32));
                     RegisterFile.updateRegister(34, (int) ((product << 32) >> 32));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mul $1,$2,$3",
            	 "Multiplication without overflow",
                BasicInstructionFormat.R_FORMAT,
                "011100 sssss ttttt fffff 00000 000010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     long product = (long) RegisterFile.getValue(operands[1])
                        * (long) RegisterFile.getValue(operands[2]);
                     RegisterFile.updateRegister(operands[0],
                        (int) ((product << 32) >> 32));
                  // Register 33 is HIGH and 34 is LOW.  Not required by MIPS; SPIM does it.
                     RegisterFile.updateRegister(33, (int) (product >> 32));
                     RegisterFile.updateRegister(34, (int) ((product << 32) >> 32));
                  }
               }));
         instructionList.add(
                new BasicInstruction("madd $1,$2",
            	 "Multiply add",
                BasicInstructionFormat.R_FORMAT,
                "011100 fffff sssss 00000 00000 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     long product = (long) RegisterFile.getValue(operands[0])
                        * (long) RegisterFile.getValue(operands[1]);
                     // Register 33 is HIGH and 34 is LOW. 
                     long contentsHiLo = Binary.twoIntsToLong(
                        RegisterFile.getValue(33), RegisterFile.getValue(34));
                     long sum = contentsHiLo + product;
                     RegisterFile.updateRegister(33, Binary.highOrderLongToInt(sum));
                     RegisterFile.updateRegister(34, Binary.lowOrderLongToInt(sum));
                  }
               }));
         instructionList.add(
                new BasicInstruction("maddu $1,$2",
            	 "Multiply add unsigned",
                BasicInstructionFormat.R_FORMAT,
                "011100 fffff sssss 00000 00000 000001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     long product = (((long) RegisterFile.getValue(operands[0]))<<32>>>32)
                        * (((long) RegisterFile.getValue(operands[1]))<<32>>>32);
                     // Register 33 is HIGH and 34 is LOW. 
                     long contentsHiLo = Binary.twoIntsToLong(
                        RegisterFile.getValue(33), RegisterFile.getValue(34));
                     long sum = contentsHiLo + product;
                     RegisterFile.updateRegister(33, Binary.highOrderLongToInt(sum));
                     RegisterFile.updateRegister(34, Binary.lowOrderLongToInt(sum));
                  }
               }));
         instructionList.add(
                new BasicInstruction("msub $1,$2",
            	 "Multiply subtract",
                BasicInstructionFormat.R_FORMAT,
                "011100 fffff sssss 00000 00000 000100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     long product = (long) RegisterFile.getValue(operands[0])
                        * (long) RegisterFile.getValue(operands[1]);
                     // Register 33 is HIGH and 34 is LOW. 
                     long contentsHiLo = Binary.twoIntsToLong(
                        RegisterFile.getValue(33), RegisterFile.getValue(34));
                     long diff = contentsHiLo - product;
                     RegisterFile.updateRegister(33, Binary.highOrderLongToInt(diff));
                     RegisterFile.updateRegister(34, Binary.lowOrderLongToInt(diff));
                  }
               }));
         instructionList.add(
                new BasicInstruction("msubu $1,$2",
            	 "Multiply subtract unsigned",
                BasicInstructionFormat.R_FORMAT,
                "011100 fffff sssss 00000 00000 000101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     long product = (((long) RegisterFile.getValue(operands[0]))<<32>>>32)
                        * (((long) RegisterFile.getValue(operands[1]))<<32>>>32);
                     // Register 33 is HIGH and 34 is LOW. 
                     long contentsHiLo = Binary.twoIntsToLong(
                        RegisterFile.getValue(33), RegisterFile.getValue(34));
                     long diff = contentsHiLo - product;
                     RegisterFile.updateRegister(33, Binary.highOrderLongToInt(diff));
                     RegisterFile.updateRegister(34, Binary.lowOrderLongToInt(diff));
                  }
               }));
         instructionList.add(
                new BasicInstruction("div $1,$2",
            	 "Division with overflow",
                BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 011010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[1]) == 0)
                     {
                     // Note: no exceptions and undefined results for zero div
                     // COD3 Appendix A says "with overflow" but MIPS 32 instruction set
                     // specification says "no arithmetic exception under any circumstances".
                        return;
                     }
                  
                  // Register 33 is HIGH and 34 is LOW
                     RegisterFile.updateRegister(33,
                        RegisterFile.getValue(operands[0])
                        % RegisterFile.getValue(operands[1]));
                     RegisterFile.updateRegister(34,
                        RegisterFile.getValue(operands[0])
                        / RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("divu $1,$2",
            	 "Division unsigned without overflow",
                BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 011011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[1]) == 0)
                     {
                     // Note: no exceptions, and undefined results for zero divide
                        return;
                     }
                     long oper1 = ((long)RegisterFile.getValue(operands[0])) << 32 >>> 32; 
                     long oper2 = ((long)RegisterFile.getValue(operands[1])) << 32 >>> 32; 
                  // Register 33 is HIGH and 34 is LOW
                     RegisterFile.updateRegister(33,
                        (int) (((oper1 % oper2) << 32) >> 32));
                     RegisterFile.updateRegister(34,
                        (int) (((oper1 / oper2) << 32) >> 32));                  
                  }
               }));
         instructionList.add(
                new BasicInstruction("mfhi $1", 
            	 "Move from HI register",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 00000 00000 fffff 00000 010000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(33));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mflo $1", 
            	 "Move from LO register",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 00000 00000 fffff 00000 010010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(34));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mthi $1", 
            	 "Move to HI register",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff 00000 00000 00000 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(33,
                        RegisterFile.getValue(operands[0]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mtlo $1", 
            	 "Move to LO register",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff 00000 00000 00000 010011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(34,
                        RegisterFile.getValue(operands[0]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("and $1,$2,$3",
            	 "Bitwise AND",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        & RegisterFile.getValue(operands[2]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("or $1,$2,$3",
            	 "Bitwise OR",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        | RegisterFile.getValue(operands[2]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("andi $1,$2,100",
            	 "Bitwise AND immediate",
                BasicInstructionFormat.I_FORMAT,
                "001100 sssss fffff tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // ANDing with 0x0000FFFF zero-extends the immediate (high 16 bits always 0).
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        & (operands[2] & 0x0000FFFF));
                  }
               }));
         instructionList.add(
                new BasicInstruction("ori $1,$2,100",
            	 "Bitwise OR immediate",
                BasicInstructionFormat.I_FORMAT,
                "001101 sssss fffff tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // ANDing with 0x0000FFFF zero-extends the immediate (high 16 bits always 0).
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        | (operands[2] & 0x0000FFFF));
                  }
               }));
         instructionList.add(
                new BasicInstruction("nor $1,$2,$3",
            	 "Bitwise NOR",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100111",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        ~(RegisterFile.getValue(operands[1])
                        | RegisterFile.getValue(operands[2])));
                  }
               }));
         instructionList.add(
                new BasicInstruction("xor $1,$2,$3",
            	 "Bitwise XOR (exclusive OR)",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 100110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        ^ RegisterFile.getValue(operands[2]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("xori $1,$2,100",
            	 "Bitwise XOR immediate",
                BasicInstructionFormat.I_FORMAT,
                "001110 sssss fffff tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // ANDing with 0x0000FFFF zero-extends the immediate (high 16 bits always 0).
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1])
                        ^ (operands[2] & 0x0000FFFF));
                  }
               }));					
         instructionList.add(
                new BasicInstruction("sll $1,$2,10",
            	 "Shift left logical",
                BasicInstructionFormat.R_FORMAT,
                "000000 00000 sssss fffff ttttt 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1]) << operands[2]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("sllv $1,$2,$3",
            	 "Shift left logical variable",
                BasicInstructionFormat.R_FORMAT,
                "000000 ttttt sssss fffff 00000 000100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // Mask all but low 5 bits of register containing shamt.
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1]) << 
                        (RegisterFile.getValue(operands[2]) & 0x0000001F));
                  }
               }));
         instructionList.add(
                new BasicInstruction("srl $1,$2,10",
            	 "Shift right logical",
                BasicInstructionFormat.R_FORMAT,
                "000000 00000 sssss fffff ttttt 000010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // must zero-fill, so use ">>>" instead of ">>".
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1]) >>> operands[2]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("sra $1,$2,10",
                "Shift right arithmetic",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 00000 sssss fffff ttttt 000011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // must sign-fill, so use ">>".
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1]) >> operands[2]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("srav $1,$2,$3",
            	 "Shift right arithmetic variable",
                BasicInstructionFormat.R_FORMAT,
                "000000 ttttt sssss fffff 00000 000111",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // Mask all but low 5 bits of register containing shamt.Use ">>" to sign-fill.
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1]) >> 
                        (RegisterFile.getValue(operands[2]) & 0x0000001F));
                  }
               }));
         instructionList.add(
                new BasicInstruction("srlv $1,$2,$3",
            	 "Shift right logical variable",
                BasicInstructionFormat.R_FORMAT,
                "000000 ttttt sssss fffff 00000 000110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // Mask all but low 5 bits of register containing shamt.Use ">>>" to zero-fill.
                     RegisterFile.updateRegister(operands[0],
                        RegisterFile.getValue(operands[1]) >>> 
                        (RegisterFile.getValue(operands[2]) & 0x0000001F));
                  }
               }));
         instructionList.add(
                new BasicInstruction("lw $1,-100($2)",
            	 "Load word",
                BasicInstructionFormat.I_FORMAT,
                "100011 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        RegisterFile.updateRegister(operands[0],
                            Globals.memory.getWord(
                            RegisterFile.getValue(operands[2]) + operands[1]));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("ll $1,-100($2)",
                "Load linked",
            	 BasicInstructionFormat.I_FORMAT,
                "110000 ttttt fffff ssssssssssssssss",
            	 // The ll (load link) command is supposed to be the front end of an atomic
            	 // operation completed by sc (store conditional), with success or failure
            	 // of the store depending on whether the memory block containing the
            	 // loaded word is modified in the meantime by a different processor.
            	 // Since MARS, like SPIM simulates only a single processor, the store
            	 // conditional will always succeed so there is no need to do anything
            	 // special here.  In that case, ll is same as lw.  And sc does the same
            	 // thing as sw except in addition it writes 1 into the source register.
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        RegisterFile.updateRegister(operands[0],
                            Globals.memory.getWord(
                            RegisterFile.getValue(operands[2]) + operands[1]));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("lwl $1,-100($2)",
                "Load word left",
            	 BasicInstructionFormat.I_FORMAT,
                "100010 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        int address = RegisterFile.getValue(operands[2]) + operands[1];
                        int result = RegisterFile.getValue(operands[0]);
                        for (int i=0; i<=address % Globals.memory.WORD_LENGTH_BYTES; i++) {
                           result = Binary.setByte(result,3-i,Globals.memory.getByte(address-i));
                        }
                        RegisterFile.updateRegister(operands[0], result);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("lwr $1,-100($2)",
                "Load word right",
            	 BasicInstructionFormat.I_FORMAT,
                "100110 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        int address = RegisterFile.getValue(operands[2]) + operands[1];
                        int result = RegisterFile.getValue(operands[0]);
                        for (int i=0; i<=3-(address % Globals.memory.WORD_LENGTH_BYTES); i++) {
                           result = Binary.setByte(result,i,Globals.memory.getByte(address+i));
                        }
                        RegisterFile.updateRegister(operands[0], result);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("sw $1,-100($2)",
                "Store word",
            	 BasicInstructionFormat.I_FORMAT,
                "101011 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        Globals.memory.setWord(
                            RegisterFile.getValue(operands[2]) + operands[1],
                            RegisterFile.getValue(operands[0]));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("sc $1,-100($2)",
                "Store conditional",
            	 BasicInstructionFormat.I_FORMAT,
                "111000 ttttt fffff ssssssssssssssss",
            	 // See comments with "ll" instruction above.  "sc" is implemented
            	 // like "sw", except that 1 is placed in the source register.
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        Globals.memory.setWord(
                            RegisterFile.getValue(operands[2]) + operands[1],
                            RegisterFile.getValue(operands[0]));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                     RegisterFile.updateRegister(operands[0],1); // always succeeds
                  }
               }));
         instructionList.add(
                new BasicInstruction("swl $1,-100($2)",
                "Store word left",
            	 BasicInstructionFormat.I_FORMAT,
                "101010 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        int address = RegisterFile.getValue(operands[2]) + operands[1];
                        int source = RegisterFile.getValue(operands[0]);
                        for (int i=0; i<=address % Globals.memory.WORD_LENGTH_BYTES; i++) {
                           Globals.memory.setByte(address-i,Binary.getByte(source,3-i));
                        }
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("swr $1,-100($2)",
                "Store word right",
            	 BasicInstructionFormat.I_FORMAT,
                "101110 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        int address = RegisterFile.getValue(operands[2]) + operands[1];
                        int source = RegisterFile.getValue(operands[0]);
                        for (int i=0; i<=3-(address % Globals.memory.WORD_LENGTH_BYTES); i++) {
                           Globals.memory.setByte(address+i,Binary.getByte(source,i));
                        }
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("lui $1,100",
                "Load upper immediate",
            	 BasicInstructionFormat.I_FORMAT,
                "001111 00000 fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0], operands[1] << 16);
                  }
               }));
         instructionList.add(
                new BasicInstruction("beq $1,$2,label",
                "Branch if equal",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000100 fffff sssss tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  
                     if (RegisterFile.getValue(operands[0])
                        == RegisterFile.getValue(operands[1]))
                     {
                        processBranch(operands[2]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("bne $1,$2,label",
                "Branch if not equal",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000101 fffff sssss tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0])
                        != RegisterFile.getValue(operands[1]))
                     {
                        processBranch(operands[2]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("bgez $1,label",
                "Branch if greater than or equal to zero",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000001 fffff 00001 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) >= 0)
                     {
                        processBranch(operands[1]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("bgezal $1,label",
                "Branch if greater then or equal to zero and link",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000001 fffff 10001 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) >= 0)
                     {  // the "and link" part
                        processReturnAddress(31);//RegisterFile.updateRegister("$ra",RegisterFile.getProgramCounter());
                        processBranch(operands[1]);
                     }
                  } 
               }));
         instructionList.add(
                new BasicInstruction("bgtz $1,label",
                "Branch if greater than zero",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000111 fffff 00000 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) > 0)
                     {
                        processBranch(operands[1]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("blez $1,label",
                "Branch if less than or equal to zero",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000110 fffff 00000 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) <= 0)
                     {
                        processBranch(operands[1]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("bltz $1,label",
                "Branch if less than zero",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000001 fffff 00000 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) < 0)
                     {
                        processBranch(operands[1]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("bltzal $1,label",
                "Branch if less than zero and link",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "000001 fffff 10000 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) < 0)
                     {  // the "and link" part
                        processReturnAddress(31);//RegisterFile.updateRegister("$ra",RegisterFile.getProgramCounter());
                        processBranch(operands[1]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("slt $1,$2,$3",
                "Set less than",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 101010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        (RegisterFile.getValue(operands[1])
                        < RegisterFile.getValue(operands[2]))
                                ? 1
                                : 0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("sltu $1,$2,$3",
                "Set less than unsigned",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 101011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int first = RegisterFile.getValue(operands[1]);
                     int second = RegisterFile.getValue(operands[2]);
                     if (first >= 0 && second >= 0 || first < 0 && second < 0)
                     {
                        RegisterFile.updateRegister(operands[0],
                            (first < second) ? 1 : 0);
                     } 
                     else
                     {
                        RegisterFile.updateRegister(operands[0],
                            (first >= 0) ? 1 : 0);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("slti $1,$2,-100",
                "Set less than immediate",
            	 BasicInstructionFormat.I_FORMAT,
                "001010 sssss fffff tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                  // 16 bit immediate value in operands[2] is sign-extended
                     RegisterFile.updateRegister(operands[0],
                        (RegisterFile.getValue(operands[1])
                        < (operands[2] << 16 >> 16))
                                ? 1
                                : 0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("sltiu $1,$2,-100",
                "Set less than immediate unsigned",
            	 BasicInstructionFormat.I_FORMAT,
                "001011 sssss fffff tttttttttttttttt",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int first = RegisterFile.getValue(operands[1]);
                  // 16 bit immediate value in operands[2] is sign-extended
                     int second = operands[2] << 16 >> 16;
                     if (first >= 0 && second >= 0 || first < 0 && second < 0)
                     {
                        RegisterFile.updateRegister(operands[0],
                            (first < second) ? 1 : 0);
                     } 
                     else
                     {
                        RegisterFile.updateRegister(operands[0],
                            (first >= 0) ? 1 : 0);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("movn $1,$2,$3",
                "Move conditional not zero",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 001011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[2])!=0)
                        RegisterFile.updateRegister(operands[0], RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movz $1,$2,$3",
                "Move conditional zero",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttttt fffff 00000 001010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[2])==0)
                        RegisterFile.updateRegister(operands[0], RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movf $1,$2",
                "Move if FP condition flag 0 false",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 sssss 000 00 fffff 00000 000001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(0)==0)
                        RegisterFile.updateRegister(operands[0], RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movf $1,$2,1",
                "Move if specified FP condition flag false",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttt 00 fffff 00000 000001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(operands[2])==0)
                        RegisterFile.updateRegister(operands[0], RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movt $1,$2",
            	 "Move if FP condition flag 0 true",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss 000 01 fffff 00000 000001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(0)==1)
                        RegisterFile.updateRegister(operands[0], RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movt $1,$2,1",
            	 "Move if specfied FP condition flag true",
                BasicInstructionFormat.R_FORMAT,
                "000000 sssss ttt 01 fffff 00000 000001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(operands[2])==1)
                        RegisterFile.updateRegister(operands[0], RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("break 100", 
            	 "Break execution with code",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 ffffffffffffffffffff 001101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {  // At this time I don't have exception processing or trap handlers
                     // so will just halt execution with a message.
                     int[] operands = statement.getOperands();
                     throw new ProcessingException(statement, "break instruction executed; code = "+
                          operands[0]+".", Exceptions.BREAKPOINT_EXCEPTION);
                  }
               }));	
         instructionList.add(
                new BasicInstruction("break", 
            	 "Break execution",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 00000 00000 00000 00000 001101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {  // At this time I don't have exception processing or trap handlers
                     // so will just halt execution with a message.
                     throw new ProcessingException(statement, "break instruction executed; no code given.",
                        Exceptions.BREAKPOINT_EXCEPTION);
                  }
               }));					
         instructionList.add(
                new BasicInstruction("syscall", 
            	 "Issue a system call",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 00000 00000 00000 00000 001100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     findAndSimulateSyscall(RegisterFile.getValue(2),statement);
                  }
               }));
         instructionList.add(
                new BasicInstruction("j target", 
            	 "Jump unconditionally",
            	 BasicInstructionFormat.J_FORMAT,
                "000010 ffffffffffffffffffffffffff",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     processJump(
                        ((RegisterFile.getProgramCounter() & 0xF0000000)
                                | (operands[0] << 2)));            
                  }
               }));
         instructionList.add(
                new BasicInstruction("jr $1", 
            	 "Jump register unconditionally",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff 00000 00000 00000 001000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     processJump(RegisterFile.getValue(operands[0]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("jal target",
                "Jump and link (puts return address in $ra)",
            	 BasicInstructionFormat.J_FORMAT,
                "000011 ffffffffffffffffffffffffff",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     processReturnAddress(31);// RegisterFile.updateRegister(31, RegisterFile.getProgramCounter());
                     processJump(
                        (RegisterFile.getProgramCounter() & 0xF0000000)
                                | (operands[0] << 2));
                  }
               }));
         instructionList.add(
                new BasicInstruction("jalr $1,$2",
                "Jump and link register (puts return address in first operand)",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 sssss 00000 fffff 00000 001001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     processReturnAddress(operands[0]);//RegisterFile.updateRegister(operands[0], RegisterFile.getProgramCounter());
                     processJump(RegisterFile.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("jalr $1",
                "Jump and link register (puts return address in $ra)",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff 00000 11111 00000 001001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     processReturnAddress(31);//RegisterFile.updateRegister(31, RegisterFile.getProgramCounter()); 
                     processJump(RegisterFile.getValue(operands[0]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("lb $1,-100($2)",
                "Load byte",
            	 BasicInstructionFormat.I_FORMAT,
                "100000 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        RegisterFile.updateRegister(operands[0],
                            Globals.memory.getByte(
                            RegisterFile.getValue(operands[2])
                                    + (operands[1] << 16 >> 16))
                                            << 24
                                            >> 24);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("lh $1,-100($2)",
                "Load halfword",
            	 BasicInstructionFormat.I_FORMAT,
                "100001 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        RegisterFile.updateRegister(operands[0],
                            Globals.memory.getHalf(
                            RegisterFile.getValue(operands[2])
                                    + (operands[1] << 16 >> 16))
                                            << 16
                                            >> 16);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("lhu $1,-100($2)",
                "Load halfword unsigned",
            	 BasicInstructionFormat.I_FORMAT,
                "100101 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                     // offset is sign-extended and loaded halfword value is zero-extended
                        RegisterFile.updateRegister(operands[0],
                            Globals.memory.getHalf(
                            RegisterFile.getValue(operands[2])
                                    + (operands[1] << 16 >> 16))
                                            & 0x0000ffff);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("lbu $1,-100($2)",
                "Load byte unsigned",
            	 BasicInstructionFormat.I_FORMAT,
                "100100 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        RegisterFile.updateRegister(operands[0],
                            Globals.memory.getByte(
                            RegisterFile.getValue(operands[2])
                                    + (operands[1] << 16 >> 16))
                                            & 0x000000ff);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("sb $1,-100($2)",
                "Store byte",
            	 BasicInstructionFormat.I_FORMAT,
                "101000 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        Globals.memory.setByte(
                            RegisterFile.getValue(operands[2])
                                    + (operands[1] << 16 >> 16),
                                    RegisterFile.getValue(operands[0])
                                            & 0x000000ff);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add(
                new BasicInstruction("sh $1,-100($2)",
                "Store halfword",
            	 BasicInstructionFormat.I_FORMAT,
                "101001 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     try
                     {
                        Globals.memory.setHalf(
                            RegisterFile.getValue(operands[2])
                                    + (operands[1] << 16 >> 16),
                                    RegisterFile.getValue(operands[0])
                                            & 0x0000ffff);
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));				
         instructionList.add(        
                new BasicInstruction("clo $1,$2", 
            	 "Count number of leading ones",
            	 BasicInstructionFormat.R_FORMAT,
            	 // MIPS32 requires rd (first) operand to appear twice in machine code.
            	 // It has to be same as rt (third) operand in machine code, but the
            	 // source statement does not have or permit third operand.
            	 // In the machine code, rd and rt are adjacent, but my mask
            	 // substitution cannot handle adjacent placement of the same source
            	 // operand (e.g. "... sssss fffff fffff ...") because it would interpret
            	 // the mask to be the total length of both (10 bits).  I could code it
            	 // to have 3 operands then define a pseudo-instruction of two operands
            	 // to translate into this, but then both would show up in instruction set
            	 // list and I don't want that.  So I will use the convention of Computer
            	 // Organization and Design 3rd Edition, Appendix A, and code the rt bits
            	 // as 0's.  The generated code does not match SPIM and would not run 
            	 // on a real MIPS machine but since I am providing no means of storing
            	 // the binary code that is not really an issue.
                "011100 sssss 00000 fffff 00000 100001",
                new SimulationCode()
               {   
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int value = RegisterFile.getValue(operands[1]);
                     int leadingOnes = 0;
                     int bitPosition = 31;
                     while (Binary.bitValue(value,bitPosition)==1 && bitPosition>=0) {
                        leadingOnes++;
                        bitPosition--;
                     }
                     RegisterFile.updateRegister(operands[0], leadingOnes);
                  }
               }));	
         instructionList.add(        
                new BasicInstruction("clz $1,$2", 
            	 "Count number of leading zeroes",
            	 BasicInstructionFormat.R_FORMAT,
            	 // See comments for "clo" instruction above.  They apply here too.
                "011100 sssss 00000 fffff 00000 100000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int value = RegisterFile.getValue(operands[1]);
                     int leadingZeros = 0;
                     int bitPosition = 31;
                     while (Binary.bitValue(value,bitPosition)==0 && bitPosition>=0) {
                        leadingZeros++;
                        bitPosition--;
                     }
                     RegisterFile.updateRegister(operands[0], leadingZeros);
                  }
               }));				
         instructionList.add(        
                new BasicInstruction("mfc0 $1,$2", 
            	 "Move from Coprocessor 0",
            	 BasicInstructionFormat.R_FORMAT,
                "010000 00000 fffff sssss 00000 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0],
                        Coprocessor0.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mtc0 $1,$2", 
            	 "Move to Coprocessor 0",
            	 BasicInstructionFormat.R_FORMAT,
                "010000 00100 fffff sssss 00000 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     Coprocessor0.updateRegister(operands[1],
                        RegisterFile.getValue(operands[0]));
                  }
               }));
      			
        /////////////////////// Floating Point Instructions Start Here ////////////////
         instructionList.add(
                new BasicInstruction("add.s $f2,$f4,$f6",
                "Floating point addition single precision", 
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fffff 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float add1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     float add2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[2]));
                     float sum = add1 + add2;
                  // overflow detected when sum is positive or negative infinity.
                  /*
                  if (sum == Float.NEGATIVE_INFINITY || sum == Float.POSITIVE_INFINITY) {
                    throw new ProcessingException(statement,"arithmetic overflow");
                  }
                  */
                     Coprocessor1.updateRegister(operands[0], Float.floatToIntBits(sum));
                  }
               }));
         instructionList.add(
                new BasicInstruction("sub.s $f2,$f4,$f6",
                "Floating point subtraction single precision",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fffff 000001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float sub1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     float sub2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[2]));
                     float diff = sub1 - sub2;
                     Coprocessor1.updateRegister(operands[0], Float.floatToIntBits(diff));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mul.s $f2,$f4,$f6",
                "Floating point multiplication single precision",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fffff 000010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float mul1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     float mul2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[2]));
                     float prod = mul1 * mul2;
                     Coprocessor1.updateRegister(operands[0], Float.floatToIntBits(prod));
                  }
               }));
         instructionList.add(
                new BasicInstruction("div.s $f2,$f4,$f6",
                "Floating point division single precision",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fffff 000011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float div1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     float div2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[2]));
                     float quot = div1 / div2;
                     Coprocessor1.updateRegister(operands[0], Float.floatToIntBits(quot));
                  }
               }));
         instructionList.add(
                new BasicInstruction("sqrt.s $f2,$f4",
            	 "Square root single precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 000100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float value = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     if (value < 0.0f) {
                        throw new ProcessingException(statement, "Invalid Operation: sqrt of negative number");
                     }
                     Coprocessor1.updateRegister(operands[0], 
                          Float.floatToIntBits( (float) Math.sqrt(value)));
                  }
               }));
         instructionList.add(
                new BasicInstruction("floor.w.s $f2,$f4",
                "Floor single precision to word",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 001111",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     Coprocessor1.updateRegister(operands[0], 
                          (int) Math.floor(Float.intBitsToFloat(Coprocessor1.getValue(operands[1]))));
                  }
               }));
         instructionList.add(
                new BasicInstruction("ceil.w.s $f2,$f4",
            	 "Ceiling single precision to word",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 001110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     Coprocessor1.updateRegister(operands[0], 
                        (int) Math.ceil(Float.intBitsToFloat(Coprocessor1.getValue(operands[1]))));
                  }
               }));
         instructionList.add(
                new BasicInstruction("round.w.s $f2,$f4",
                "Round single precision to word",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 001100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { // MIPS32 documentation (and IEEE 754) states that round rounds to the nearest but when
                    // both are equally near it rounds to the even one!  SPIM rounds -4.5, -5.5,
                    // 4.5 and 5.5 to (-4, -5, 5, 6).  Curiously, it rounds -5.1 to -4 and -5.6 to -5. 
                    // Until MARS 3.5, I used Math.round, which rounds to nearest but when both are
                    // equal it rounds toward positive infinity.  With Release 3.5, I painstakingly
                    // carry out the MIPS and IEEE 754 standard.
                     int[] operands = statement.getOperands();
                     float floatValue = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     int below=0, above=0, round = Math.round(floatValue);
                  	// According to MIPS32 spec, if any of these conditions is true, set
                  	// Invalid Operation in the FCSR (Floating point Control/Status Register) and
                  	// set result to be 2^31-1.  MARS does not implement this register (as of release 3.4.1).
                  	// It also mentions the "Invalid Operation Enable bit" in FCSR, that, if set, results
                  	// in immediate exception instead of default value.  
                     if ( Float.isNaN(floatValue) 
                          || Float.isInfinite(floatValue)
                          || floatValue < (float) Integer.MIN_VALUE 
                     	  || floatValue > (float) Integer.MAX_VALUE ) {
                        round = Integer.MAX_VALUE;
                     } 
                     else {
                        Float floatObj = new Float(floatValue);
                        // If we are EXACTLY in the middle, then round to even!  To determine this,
                        // find next higher integer and next lower integer, then see if distances 
                        // are exactly equal.
                        if (floatValue < 0.0F) {
                           above = floatObj.intValue(); // truncates
                           below = above - 1;
                        } 
                        else {
                           below = floatObj.intValue(); // truncates
                           above = below + 1;
                        }
                        if (floatValue - below == above - floatValue) { // exactly in the middle?
                           round = (above%2 == 0) ? above : below;
                        }
                     }
                     Coprocessor1.updateRegister(operands[0], round);
                  }
               }));
         instructionList.add(
                new BasicInstruction("trunc.w.s $f2,$f4",
                "Truncate single precision to word",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 001101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     Coprocessor1.updateRegister(operands[0], 
                        (int) Float.intBitsToFloat(Coprocessor1.getValue(operands[1])));
                  }
               }));
         instructionList.add(
                new BasicInstruction("add.d $f2,$f4,$f6",
            	 "Floating point addition double precision",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fffff 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double add1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     double add2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[2]+1),Coprocessor1.getValue(operands[2])));
                     double sum  = add1 + add2;
                     long longSum = Double.doubleToLongBits(sum);
                     Coprocessor1.updateRegister(operands[0]+1, Binary.highOrderLongToInt(longSum));
                     Coprocessor1.updateRegister(operands[0], Binary.lowOrderLongToInt(longSum));
                  }
               }));
         instructionList.add(
                new BasicInstruction("sub.d $f2,$f4,$f6",
            	 "Floating point subtraction double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fffff 000001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double sub1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     double sub2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[2]+1),Coprocessor1.getValue(operands[2])));
                     double diff = sub1 - sub2;
                     long longDiff = Double.doubleToLongBits(diff);
                     Coprocessor1.updateRegister(operands[0]+1, Binary.highOrderLongToInt(longDiff));
                     Coprocessor1.updateRegister(operands[0], Binary.lowOrderLongToInt(longDiff));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mul.d $f2,$f4,$f6",
            	 "Floating point multiplication double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fffff 000010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double mul1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     double mul2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[2]+1),Coprocessor1.getValue(operands[2])));
                     double prod  = mul1 * mul2;
                     long longProd = Double.doubleToLongBits(prod);
                     Coprocessor1.updateRegister(operands[0]+1, Binary.highOrderLongToInt(longProd));
                     Coprocessor1.updateRegister(operands[0], Binary.lowOrderLongToInt(longProd));
                  }
               }));
         instructionList.add(
                new BasicInstruction("div.d $f2,$f4,$f6",
            	 "Floating point division double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fffff 000011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double div1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     double div2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[2]+1),Coprocessor1.getValue(operands[2])));
                     double quot  = div1 / div2;
                     long longQuot = Double.doubleToLongBits(quot);
                     Coprocessor1.updateRegister(operands[0]+1, Binary.highOrderLongToInt(longQuot));
                     Coprocessor1.updateRegister(operands[0], Binary.lowOrderLongToInt(longQuot));
                  }
               }));
         instructionList.add(
                new BasicInstruction("sqrt.d $f2,$f4",
            	 "Square root double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 000100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double value = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     if (value < 0.0) {
                        throw new ProcessingException(statement, "Invalid Operation: sqrt of negative number");
                     }
                     long longSqrt = Double.doubleToLongBits(Math.sqrt(value));
                     Coprocessor1.updateRegister(operands[0]+1, Binary.highOrderLongToInt(longSqrt));
                     Coprocessor1.updateRegister(operands[0], Binary.lowOrderLongToInt(longSqrt));
                  }
               }));
         instructionList.add(
                new BasicInstruction("floor.w.d $f2,$f4",
            	 "Floor double precision to word",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 001111",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     double value = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     Coprocessor1.updateRegister(operands[0]+1, 0);
                     Coprocessor1.updateRegister(operands[0], (int) Math.floor(value));
                  }
               }));
         instructionList.add(
                new BasicInstruction("ceil.w.d $f2,$f4",
            	 "Ceiling double precision to word",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 001110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     double value = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     Coprocessor1.updateRegister(operands[0]+1, 0);
                     Coprocessor1.updateRegister(operands[0], (int) Math.ceil(value));
                  }
               }));
         instructionList.add(
                new BasicInstruction("round.w.d $f2,$f4",
            	 "Round double precision to word",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 001100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { // See comments in round.w.s above, concerning MIPS and IEEE 754 standard. 
                    // Until MARS 3.5, I used Math.round, which rounds to nearest but when both are
                    // equal it rounds toward positive infinity.  With Release 3.5, I painstakingly
                    // carry out the MIPS and IEEE 754 standard (round to nearest/even).
                     int[] operands = statement.getOperands();
                     double doubleValue = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     int below=0, above=0; 
                     int round = (int) Math.round(doubleValue);
                  	// See comments in round.w.s above concerning FSCR...  
                     if ( Double.isNaN(doubleValue) 
                          || Double.isInfinite(doubleValue)
                          || doubleValue < (double) Integer.MIN_VALUE 
                     	  || doubleValue > (double) Integer.MAX_VALUE ) {
                        round = Integer.MAX_VALUE;
                     } 
                     else {
                        Double doubleObj = new Double(doubleValue);
                        // If we are EXACTLY in the middle, then round to even!  To determine this,
                        // find next higher integer and next lower integer, then see if distances 
                        // are exactly equal.
                        if (doubleValue < 0.0) {
                           above = doubleObj.intValue(); // truncates
                           below = above - 1;
                        } 
                        else {
                           below = doubleObj.intValue(); // truncates
                           above = below + 1;
                        }
                        if (doubleValue - below == above - doubleValue) { // exactly in the middle?
                           round = (above%2 == 0) ? above : below;
                        }
                     }
                     Coprocessor1.updateRegister(operands[0]+1, 0);
                     Coprocessor1.updateRegister(operands[0], round);
                  }
               }));
         instructionList.add(
                new BasicInstruction("trunc.w.d $f2,$f4",
            	 "Truncate double precision to word",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 001101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     double value = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     Coprocessor1.updateRegister(operands[0]+1, 0);
                     Coprocessor1.updateRegister(operands[0], (int) value);
                  }
               }));
         instructionList.add(
                new BasicInstruction("bc1t label",
            	 "Branch if FP condition flag 0 true (BC1T, not BCLT)",
                BasicInstructionFormat.I_BRANCH_FORMAT,
                "010001 01000 00001 ffffffffffffffff",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(0)==1)
                     {
                        processBranch(operands[0]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("bc1t 1,label",
                "Branch if specified FP condition flag true (BC1T, not BCLT)",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "010001 01000 fff 01 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(operands[0])==1)
                     {
                        processBranch(operands[1]);
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("bc1f label",
                "Branch if FP condition flag 0 false (BC1F, not BCLF)",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "010001 01000 00000 ffffffffffffffff",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(0)==0)
                     {
                        processBranch(operands[0]);
                     }
                  
                  }
               }));
         instructionList.add(
                new BasicInstruction("bc1f 1,label",
                "Branch if specified FP condition flag false (BC1F, not BCLF)",
            	 BasicInstructionFormat.I_BRANCH_FORMAT,
                "010001 01000 fff 00 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(operands[0])==0)
                     {
                        processBranch(operands[1]);
                     }
                  
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.eq.s $f2,$f4",
                "Compare equal single precision, result in condition flag 0",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 sssss fffff 00000 110010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float op1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[0]));
                     float op2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     if (op1 == op2) 
                        Coprocessor1.setConditionFlag(0);
                     else
                        Coprocessor1.clearConditionFlag(0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.eq.s 1,$f2,$f4",
                 "Compare equal single precision, result in specified condition flag",
               BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fff 00 11 0010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float op1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     float op2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[2]));
                     if (op1 == op2) 
                        Coprocessor1.setConditionFlag(operands[0]);
                     else
                        Coprocessor1.clearConditionFlag(operands[0]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.le.s $f2,$f4",
            	 "Compare less or equal single precision, result in condition flag 0",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 sssss fffff 00000 111110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float op1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[0]));
                     float op2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     if (op1 <= op2) 
                        Coprocessor1.setConditionFlag(0);
                     else
                        Coprocessor1.clearConditionFlag(0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.le.s 1,$f2,$f4",
            	 "Compare less or equal single precision, result in specified condition flag",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fff 00 111110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float op1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     float op2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[2]));
                     if (op1 <= op2) 
                        Coprocessor1.setConditionFlag(operands[0]);
                     else
                        Coprocessor1.clearConditionFlag(operands[0]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.lt.s $f2,$f4",
            	 "Compare less than single precision, result in condition flag 0",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 sssss fffff 00000 111100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float op1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[0]));
                     float op2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     if (op1 < op2) 
                        Coprocessor1.setConditionFlag(0);
                     else
                        Coprocessor1.clearConditionFlag(0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.lt.s 1,$f2,$f4",
                "Compare less than single precision, result in specified condition flag",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fff 00 111100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     float op1 = Float.intBitsToFloat(Coprocessor1.getValue(operands[1]));
                     float op2 = Float.intBitsToFloat(Coprocessor1.getValue(operands[2]));
                     if (op1 < op2) 
                        Coprocessor1.setConditionFlag(operands[0]);
                     else
                        Coprocessor1.clearConditionFlag(operands[0]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.eq.d $f2,$f4",
            	 "Compare equal double precision, result in condition flag 0",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 sssss fffff 00000 110010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double op1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[0]+1),Coprocessor1.getValue(operands[0])));
                     double op2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     if (op1 == op2) 
                        Coprocessor1.setConditionFlag(0);
                     else
                        Coprocessor1.clearConditionFlag(0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.eq.d 1,$f2,$f4",
            	 "Compare equal double precision, result in specified condition flag",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fff 00 110010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double op1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     double op2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[2]+1),Coprocessor1.getValue(operands[2])));
                     if (op1 == op2) 
                        Coprocessor1.setConditionFlag(operands[0]);
                     else
                        Coprocessor1.clearConditionFlag(operands[0]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.le.d $f2,$f4",
            	 "Compare less or equal double precision, result in condition flag 0",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 sssss fffff 00000 111110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double op1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[0]+1),Coprocessor1.getValue(operands[0])));
                     double op2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     if (op1 <= op2) 
                        Coprocessor1.setConditionFlag(0);
                     else
                        Coprocessor1.clearConditionFlag(0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.le.d 1,$f2,$f4",
            	 "Compare less or equal double precision, result in specified condition flag",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fff 00 111110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double op1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     double op2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[2]+1),Coprocessor1.getValue(operands[2])));
                     if (op1 <= op2) 
                        Coprocessor1.setConditionFlag(operands[0]);
                     else
                        Coprocessor1.clearConditionFlag(operands[0]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.lt.d $f2,$f4",
            	 "Compare less than double precision, result in condition flag 0",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 sssss fffff 00000 111100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double op1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[0]+1),Coprocessor1.getValue(operands[0])));
                     double op2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     if (op1 < op2) 
                        Coprocessor1.setConditionFlag(0);
                     else
                        Coprocessor1.clearConditionFlag(0);
                  }
               }));
         instructionList.add(
                new BasicInstruction("c.lt.d 1,$f2,$f4",
            	 "Compare less than double precision, result in specified condition flag",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fff 00 111100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[1]%2==1 || operands[2]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                     double op1 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     double op2 = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[2]+1),Coprocessor1.getValue(operands[2])));
                     if (op1 < op2) 
                        Coprocessor1.setConditionFlag(operands[0]);
                     else
                        Coprocessor1.clearConditionFlag(operands[0]);
                  }
               }));
         instructionList.add(
                new BasicInstruction("abs.s $f2,$f4",
            	 "Floating point absolute value single precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 000101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                  	// I need only clear the high order bit!
                     Coprocessor1.updateRegister(operands[0], 
                                         Coprocessor1.getValue(operands[1]) & Integer.MAX_VALUE);
                  }
               }));
         instructionList.add(
                new BasicInstruction("abs.d $f2,$f4",
            	 "Floating point absolute value double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 000101",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "all registers must be even");
                     }
                  	// I need only clear the high order bit of high word register!
                     Coprocessor1.updateRegister(operands[0]+1, 
                                         Coprocessor1.getValue(operands[1]+1) & Integer.MAX_VALUE);
                     Coprocessor1.updateRegister(operands[0], 
                                         Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("cvt.d.s $f2,$f4",
            	 "Convert from single precision to double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 100001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                  	// convert single precision in $f4 to double stored in $f2
                     long result = Double.doubleToLongBits(
                          (double)Float.intBitsToFloat(Coprocessor1.getValue(operands[1])));
                     Coprocessor1.updateRegister(operands[0]+1, Binary.highOrderLongToInt(result));
                     Coprocessor1.updateRegister(operands[0], Binary.lowOrderLongToInt(result));
                  }
               }));
         instructionList.add(
                new BasicInstruction("cvt.d.w $f2,$f4",
            	 "Convert from word to double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10100 00000 sssss fffff 100001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                  	// convert integer to double (interpret $f4 value as int?)
                     long result = Double.doubleToLongBits(
                          (double)Coprocessor1.getValue(operands[1]));
                     Coprocessor1.updateRegister(operands[0]+1, Binary.highOrderLongToInt(result));
                     Coprocessor1.updateRegister(operands[0], Binary.lowOrderLongToInt(result));
                  }
               }));
         instructionList.add(
                new BasicInstruction("cvt.s.d $f2,$f4",
                "Convert from double precision to single precision",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 100000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                  	// convert double precision in $f4 to single stored in $f2
                     if (operands[1]%2==1) {
                        throw new ProcessingException(statement, "source register must be even");
                     }
                     double val = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     Coprocessor1.updateRegister(operands[0], Float.floatToIntBits((float)val));
                  }
               }));
         instructionList.add(
                new BasicInstruction("cvt.s.w $f2,$f4",
            	 "Convert from word to single precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10100 00000 sssss fffff 100000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                  	// convert integer to single (interpret $f4 value as int?)
                     Coprocessor1.updateRegister(operands[0], 
                         Float.floatToIntBits((float)Coprocessor1.getValue(operands[1])));
                  }
               }));
         instructionList.add(
                new BasicInstruction("cvt.w.d $f2,$f4",
            	 "Convert from double precision to word",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 100100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                  	// convert double precision in $f4 to integer stored in $f2
                     if (operands[1]%2==1) {
                        throw new ProcessingException(statement, "source register must be even");
                     }
                     double val = Double.longBitsToDouble(Binary.twoIntsToLong(
                              Coprocessor1.getValue(operands[1]+1),Coprocessor1.getValue(operands[1])));
                     Coprocessor1.updateRegister(operands[0], (int) val);
                  }
               }));
         instructionList.add(
                new BasicInstruction("cvt.w.s $f2,$f4",
            	 "Convert from single precision to word",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 100100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                  	// convert single precision in $f4 to integer stored in $f2
                     Coprocessor1.updateRegister(operands[0], 
                             (int)Float.intBitsToFloat(Coprocessor1.getValue(operands[1])));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mov.d $f2,$f4",
            	 "Move floating point double precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 000110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                     Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                     Coprocessor1.updateRegister(operands[0]+1, Coprocessor1.getValue(operands[1]+1));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movf.d $f2,$f4",
            	 "Move floating point double precision if condition flag 0 false",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 000 00 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                     if (Coprocessor1.getConditionFlag(0)==0) {
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                        Coprocessor1.updateRegister(operands[0]+1, Coprocessor1.getValue(operands[1]+1));
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("movf.d $f2,$f4,1",
            	 "Move floating point double precision if specified condition flag false",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttt 00 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                     if (Coprocessor1.getConditionFlag(operands[2])==0) {
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                        Coprocessor1.updateRegister(operands[0]+1, Coprocessor1.getValue(operands[1]+1));
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("movt.d $f2,$f4",
            	 "Move floating point double precision if condition flag 0 true",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 000 01 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                     if (Coprocessor1.getConditionFlag(0)==1) {
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                        Coprocessor1.updateRegister(operands[0]+1, Coprocessor1.getValue(operands[1]+1));
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("movt.d $f2,$f4,1",
            	 "Move floating point double precision if specified condition flag true",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttt 01 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                     if (Coprocessor1.getConditionFlag(operands[2])==1) {
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                        Coprocessor1.updateRegister(operands[0]+1, Coprocessor1.getValue(operands[1]+1));
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("movn.d $f2,$f4,$3",
            	 "Move floating point double precision if register not zero",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fffff 010011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                     if (RegisterFile.getValue(operands[2])!=0) {
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                        Coprocessor1.updateRegister(operands[0]+1, Coprocessor1.getValue(operands[1]+1));
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("movz.d $f2,$f4,$3",
            	 "Move floating point double precision if register zero",
                BasicInstructionFormat.R_FORMAT,
                "010001 10001 ttttt sssss fffff 010010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                     if (RegisterFile.getValue(operands[2])==0) {
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                        Coprocessor1.updateRegister(operands[0]+1, Coprocessor1.getValue(operands[1]+1));
                     }
                  }
               }));
         instructionList.add(
                new BasicInstruction("mov.s $f2,$f4",
            	 "Move floating point single precision",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 000110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movf.s $f2,$f4",
            	 "Move floating point single precision if condition flag 0 false",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 000 00 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(0)==0)
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movf.s $f2,$f4,1",
            	 "Move floating point double precision if specified condition flag false",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttt 00 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(operands[2])==0)
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movt.s $f2,$f4",
            	 "Move floating point single precision if condition flag 0 true",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 000 01 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(0)==1)
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movt.s $f2,$f4,1",
            	 "Move floating point single precision if specified condition flag true",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttt 01 sssss fffff 010001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (Coprocessor1.getConditionFlag(operands[2])==1)
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movn.s $f2,$f4,$3",
            	 "Move floating point single precision if register not zero",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fffff 010011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[2])!=0)
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("movz.s $f2,$f4,$3",
            	 "Move floating point single precision if register zero",
                BasicInstructionFormat.R_FORMAT,
                "010001 10000 ttttt sssss fffff 010010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[2])==0)
                        Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mfc1 $1,$f2",
                "Move from Coprocessor 1 (FPU)",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 00000 fffff sssss 00000 000000", 
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     RegisterFile.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("mtc1 $1,$f2",
                "Move to Coprocessor 1 (FPU)",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 00100 fffff sssss 00000 000000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     Coprocessor1.updateRegister(operands[1], RegisterFile.getValue(operands[0]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("neg.d $f2,$f4",
                "Floating point negate double precision",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10001 00000 sssss fffff 000111",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1 || operands[1]%2==1) {
                        throw new ProcessingException(statement, "both registers must be even");
                     }
                  	// flip the sign bit of the second register (high order word) of the pair
                     int value = Coprocessor1.getValue(operands[1]+1);
                     Coprocessor1.updateRegister(operands[0]+1, 
                          ((value < 0) ? (value & Integer.MAX_VALUE) : (value | Integer.MIN_VALUE)));
                     Coprocessor1.updateRegister(operands[0], Coprocessor1.getValue(operands[1]));
                  }
               }));
         instructionList.add(
                new BasicInstruction("neg.s $f2,$f4",
                "Floating point negate single precision",
            	 BasicInstructionFormat.R_FORMAT,
                "010001 10000 00000 sssss fffff 000111",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     int value = Coprocessor1.getValue(operands[1]);
                  	// flip the sign bit
                     Coprocessor1.updateRegister(operands[0], 
                          ((value < 0) ? (value & Integer.MAX_VALUE) : (value | Integer.MIN_VALUE)));
                  }
               }));
         instructionList.add(
                new BasicInstruction("lwc1 $f2,-100($2)",
                "Load word from Coprocessor 1 (FPU)",
            	 BasicInstructionFormat.I_FORMAT,
                "110001 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     try
                     {
                        Coprocessor1.updateRegister(operands[0],
                            Globals.memory.getWord(
                            RegisterFile.getValue(operands[2]) + operands[1]));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));		 
         instructionList.add(// no printed reference, got opcode from SPIM
                new BasicInstruction("ldc1 $f2,-100($2)",
            	 "Load double word Coprocessor 1 (FPU)",
                BasicInstructionFormat.I_FORMAT,
                "110101 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1) {
                        throw new ProcessingException(statement, "double register must be even");
                     }
                     try
                     {
                        Coprocessor1.updateRegister(operands[0],
                            Globals.memory.getWord(
                            RegisterFile.getValue(operands[2]) + operands[1]));
                        Coprocessor1.updateRegister(operands[0]+1,
                            Globals.memory.getWord(
                            RegisterFile.getValue(operands[2]) + operands[1] + 4));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));	 
         instructionList.add(
                new BasicInstruction("swc1 $f2,-100($2)",
            	 "Store word from Coprocesor 1 (FPU)",
                BasicInstructionFormat.I_FORMAT,
                "111001 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     try
                     {
                        Globals.memory.setWord(
                            RegisterFile.getValue(operands[2]) + operands[1],
                            Coprocessor1.getValue(operands[0]));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
         instructionList.add( // no printed reference, got opcode from SPIM
                new BasicInstruction("sdc1 $f2,-100($2)",
            	 "Store double word from Coprocessor 1 (FPU)",
                BasicInstructionFormat.I_FORMAT,
                "111101 ttttt fffff ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (operands[0]%2==1) {
                        throw new ProcessingException(statement, "double register must be even");
                     }
                     try
                     {
                        Globals.memory.setWord(
                            RegisterFile.getValue(operands[2]) + operands[1],
                            Coprocessor1.getValue(operands[0]));
                        Globals.memory.setWord(
                            RegisterFile.getValue(operands[2]) + operands[1] + 4,
                            Coprocessor1.getValue(operands[0]+1));
                     } 
                         catch (AddressErrorException e)
                        {
                           throw new ProcessingException(statement, e);
                        }
                  }
               }));
      	////////////////////////////  THE TRAP INSTRUCTIONS & ERET  ////////////////////////////
         instructionList.add(
                new BasicInstruction("teq $1,$2",
                "Trap if register contents are equal",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 110100",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) == RegisterFile.getValue(operands[1]))
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     } 	                     
                  }
               }));
         instructionList.add(
                new BasicInstruction("teqi $1,-100",
            	 "Trap if register contents equal to immediate",
                BasicInstructionFormat.I_FORMAT,
                "000001 fffff 01100 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) == (operands[1] << 16 >> 16)) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                
                  }
               }));
         instructionList.add(
                new BasicInstruction("tne $1,$2",
                "Trap if register contents are not equal",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 110110",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) != RegisterFile.getValue(operands[1]))
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                      
                  }
               }));        
         instructionList.add(
                new BasicInstruction("tnei $1,-100",
            	 "Trap if register contents not equal to immediate",
                BasicInstructionFormat.I_FORMAT,
                "000001 fffff 01110 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) != (operands[1] << 16 >> 16)) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                     
                  }
               }));
         instructionList.add(
                new BasicInstruction("tge $1,$2",
                "Trap if first register contents greater or equal",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 110000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) >= RegisterFile.getValue(operands[1]))
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     } 	                     
                  }
               }));
         instructionList.add(
                new BasicInstruction("tgeu $1,$2",
                "Trap if first register contents greater or equal, unsigned",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 110001",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     int first = RegisterFile.getValue(operands[0]);
                     int second = RegisterFile.getValue(operands[1]);
                  	// if signs same, do straight compare; if signs differ & first negative then first greater else second
                     if ((first >= 0 && second >= 0 || first < 0 && second < 0) ? (first >= second) : (first < 0) ) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                      
                  }
               }));
         instructionList.add(
                new BasicInstruction("tgei $1,-100",
            	 "Trap if register contents greater than or equal to immediate",
                BasicInstructionFormat.I_FORMAT,
                "000001 fffff 01000 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) >= (operands[1] << 16 >> 16)) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                    
                  }
               }));
         instructionList.add(
                new BasicInstruction("tgeiu $1,-100",
                "Trap if register contents greater or equal to immediate, unsigned",
            	 BasicInstructionFormat.I_FORMAT,
                "000001 fffff 01001 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int first = RegisterFile.getValue(operands[0]);
                     // 16 bit immediate value in operands[1] is sign-extended
                     int second = operands[1] << 16 >> 16;
                  	// if signs same, do straight compare; if signs differ & first negative then first greater else second
                     if ((first >= 0 && second >= 0 || first < 0 && second < 0) ? (first >= second) : (first < 0) ) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                
                  }
               }));
         instructionList.add(
                new BasicInstruction("tlt $1,$2",
                "Trap if first register contents less",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 110010",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) < RegisterFile.getValue(operands[1]))
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     } 	                     
                  }
               }));
         instructionList.add(
                new BasicInstruction("tltu $1,$2",
                "Trap if first register contents less, unsigned",
            	 BasicInstructionFormat.R_FORMAT,
                "000000 fffff sssss 00000 00000 110011",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  { 
                     int[] operands = statement.getOperands();
                     int first = RegisterFile.getValue(operands[0]);
                     int second = RegisterFile.getValue(operands[1]);
                  	// if signs same, do straight compare; if signs differ & first positive then first is less else second
                     if ((first >= 0 && second >= 0 || first < 0 && second < 0) ? (first < second) : (first >= 0) ) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                    
                  }
               }));
         instructionList.add(
                new BasicInstruction("tlti $1,-100",
            	 "Trap if register contents less than immediate",
                BasicInstructionFormat.I_FORMAT,
                "000001 fffff 01010 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     if (RegisterFile.getValue(operands[0]) < (operands[1] << 16 >> 16)) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     } 	                     
                  }
               }));
         instructionList.add(
                new BasicInstruction("tltiu $1,-100",
                "Trap if register contents less than immediate, unsigned",
            	 BasicInstructionFormat.I_FORMAT,
                "000001 fffff 01011 ssssssssssssssss",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     int[] operands = statement.getOperands();
                     int first = RegisterFile.getValue(operands[0]);
                     // 16 bit immediate value in operands[1] is sign-extended
                     int second = operands[1] << 16 >> 16;
                  	// if signs same, do straight compare; if signs differ & first positive then first is less else second
                     if ((first >= 0 && second >= 0 || first < 0 && second < 0) ? (first < second) : (first >= 0) ) 
                     {
                        throw new ProcessingException(statement,
                            "trap",Exceptions.TRAP_EXCEPTION);
                     }                   
                  }
               }));
         instructionList.add(
                new BasicInstruction("eret", 
            	 "Exception return",
            	 BasicInstructionFormat.R_FORMAT,
                "010000 1 0000000000000000000 011000",
                new SimulationCode()
               {
                   public void simulate(ProgramStatement statement) throws ProcessingException
                  {
                     // set EXL bit (bit 1) in Status register to 0 and set PC to EPC
                     Coprocessor0.updateRegister(Coprocessor0.STATUS, 
                                                 Binary.clearBit(Coprocessor0.getValue(Coprocessor0.STATUS), Coprocessor0.EXCEPTION_LEVEL));
                     RegisterFile.setProgramCounter(Coprocessor0.getValue(Coprocessor0.EPC));
                  }
               }));
      			
        ////////////// READ PSEUDO-INSTRUCTION SPECS FROM DATA FILE AND ADD //////////////////////
         addPseudoInstructions();
      	
        ////////////// GET AND CREATE LIST OF SYSCALL FUNCTION OBJECTS ////////////////////
         syscallLoader = new SyscallLoader();
         syscallLoader.loadSyscalls();
      	
        // Initialization step.  Create token list for each instruction example.  This is
        // used by parser to determine user program correct syntax.
         for (int i = 0; i < instructionList.size(); i++)
         {
            Instruction inst = (Instruction) instructionList.get(i);
            inst.createExampleTokenList();
         }
      
      }
   	
   	
    /*  METHOD TO ADD PSEUDO-INSTRUCTIONS
    */
   
       private void addPseudoInstructions()
      {
         InputStream is = null;
         BufferedReader in = null;
         try
         {
            // leading "/" prevents package name being prepended to filepath.
            is = this.getClass().getResourceAsStream("/PseudoOps.txt");
            in = new BufferedReader(new InputStreamReader(is));
         } 
             catch (NullPointerException e)
            {
               System.out.println(
                    "Error: MIPS pseudo-instruction file PseudoOps.txt not found.");
               System.exit(0);
            }
         try
         {
            String line, pseudoOp, template, firstTemplate, token;
            String description;
            StringTokenizer tokenizer;
            while ((line = in.readLine()) != null) {
                // skip over: comment lines, empty lines, lines starting with blank.
               if (!line.startsWith("#") && !line.startsWith(" ")
                        && line.length() > 0)  {  
                  description = "";
                  tokenizer = new StringTokenizer(line, "\t");
                  pseudoOp = tokenizer.nextToken();
                  template = "";
                  firstTemplate = null;
                  while (tokenizer.hasMoreTokens()) {
                     token = tokenizer.nextToken();
                     if (token.startsWith("#")) {  
                        // Optional description must be last token in the line.
                        description = token.substring(1);
                        break;
                     }
                     if (token.startsWith("COMPACT")) {
                        // has second template for Compact (16-bit) memory config -- added DPS 3 Aug 2009
                        firstTemplate = template;
                        template = "";
                        continue;
                     } 
                     template = template + token;
                     if (tokenizer.hasMoreTokens()) {
                        template = template + "\n";
                     }
                  }
                  ExtendedInstruction inst = (firstTemplate == null)
                         ? new ExtendedInstruction(pseudoOp, template, description)
                     	 : new ExtendedInstruction(pseudoOp, firstTemplate, template, description);
                  instructionList.add(inst);
						//if (firstTemplate != null) System.out.println("\npseudoOp: "+pseudoOp+"\ndefault template:\n"+firstTemplate+"\ncompact template:\n"+template);
               }
            }
            in.close();
         } 
             catch (IOException ioe)
            {
               System.out.println(
                    "Internal Error: MIPS pseudo-instructions could not be loaded.");
               System.exit(0);
            } 
             catch (Exception ioe)
            {
               System.out.println(
                    "Error: Invalid MIPS pseudo-instruction specification.");
               System.exit(0);
            }
      
      }
   	
    /**
     *  Given an operator mnemonic, will return the corresponding Instruction object(s)
     *  from the instruction set.  Uses straight linear search technique.
     *  @param name operator mnemonic (e.g. addi, sw,...)
     *  @return list of corresponding Instruction object(s), or null if not found.
     */
       public ArrayList matchOperator(String name)
      {
         ArrayList matchingInstructions = null;
        // Linear search for now....
         for (int i = 0; i < instructionList.size(); i++)
         {
            if (((Instruction) instructionList.get(i)).getName().equals(name))
            {
               if (matchingInstructions == null) 
                  matchingInstructions = new ArrayList();
               matchingInstructions.add(instructionList.get(i));
            }
         }
         return matchingInstructions;
      
      }
   	
   	/*
   	 * Method to find and invoke a syscall given its service number.  Each syscall
   	 * function is represented by an object in an array list.  Each object is of
   	 * a class that implements Syscall or extends AbstractSyscall.
   	 */
   	 
       private void findAndSimulateSyscall(int number, ProgramStatement statement) 
                                                        throws ProcessingException {
         Syscall service = syscallLoader.findSyscall(number);
         if (service != null) {
            service.simulate(statement);
            return;
         }
         throw new ProcessingException(statement,
              "invalid or unimplemented syscall service: " +
              number + " ", Exceptions.SYSCALL_EXCEPTION);
      }
   	
   	/*
   	 * Method to process a successful branch condition.  DO NOT USE WITH JUMP
   	 * INSTRUCTIONS!  The branch operand is a relative displacement in words
   	 * whereas the jump operand is an absolute address in bytes.
   	 *
   	 * The parameter is displacement operand from instruction.
   	 *
   	 * Handles delayed branching if that setting is enabled.
   	 */
   	 // 4 January 2008 DPS:  The subtraction of 4 bytes (instruction length) after
   	 // the shift has been removed.  It is left in as commented-out code below.
   	 // This has the effect of always branching as if delayed branching is enabled, 
   	 // even if it isn't.  This mod must work in conjunction with
   	 // ProgramStatement.java, buildBasicStatementFromBasicInstruction() method near
   	 // the bottom (currently line 194, heavily commented).
   	 
       private void processBranch(int displacement) {
         if (Globals.getSettings().getDelayedBranchingEnabled()) {
            // Register the branch target address (absolute byte address).
            DelayedBranch.register(RegisterFile.getProgramCounter() + (displacement << 2));
         } 
         else {
            // Decrement needed because PC has already been incremented
            RegisterFile.setProgramCounter(
                RegisterFile.getProgramCounter()
                  + (displacement << 2)); // - Instruction.INSTRUCTION_LENGTH);	
         }	 
      }
   
   	/*
   	 * Method to process a jump.  DO NOT USE WITH BRANCH INSTRUCTIONS!  
   	 * The branch operand is a relative displacement in words
   	 * whereas the jump operand is an absolute address in bytes.
   	 *
   	 * The parameter is jump target absolute byte address.
   	 *
   	 * Handles delayed branching if that setting is enabled.
   	 */
   	 
       private void processJump(int targetAddress) {
         if (Globals.getSettings().getDelayedBranchingEnabled()) {
            DelayedBranch.register(targetAddress);
         } 
         else {
            RegisterFile.setProgramCounter(targetAddress);
         }	 
      }
   
   	/*
   	 * Method to process storing of a return address in the given
   	 * register.  This is used only by the "and link"
   	 * instructions: jal, jalr, bltzal, bgezal.  If delayed branching
   	 * setting is off, the return address is the address of the
   	 * next instruction (e.g. the current PC value).  If on, the
   	 * return address is the instruction following that, to skip over
   	 * the delay slot.
   	 *
   	 * The parameter is register number to receive the return address.
   	 */
   	 
       private void processReturnAddress(int register) {
         RegisterFile.updateRegister(register, RegisterFile.getProgramCounter() +
                 ((Globals.getSettings().getDelayedBranchingEnabled()) ? 
            	  Instruction.INSTRUCTION_LENGTH : 0) );	 
      }
   	
   }

